﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using CapaLogica.CL.Grupo;
using CapaLogica.CL.Carrera;
using CapaLogica.CL.UtilidadesGenerales;
using CapaLogica.CL.Rol;
using CapaLogica.CL.Foro;
using System.Data.SqlClient;



namespace CapaLogica.CL.Usuario
{
    public class GestorUsuario
    {
        public static bool registrarUsuario(String pcedula, String pnombre, String papellido1, String papellido2,
            String pgenero, DateTime pfechNaci, int prol, String pcorreo, List<int> listacarreras)
        {
            bool result = true;

            try
            {
                string pwd = Cl_Usuario.CreateRandomPassword(5);
                string pwdMD5= Modulo.Encriptar(pwd, true);

                Cl_Usuario objUsuario = new Cl_Usuario(pcedula, pnombre, papellido1, papellido2, pgenero, pfechNaci, prol, pcorreo, pwdMD5);
                int codUsuario = UsuarioPersistente.registrarUsuario(objUsuario, Session.Id);

                Modulo.enviarCorreo(pwd, objUsuario.CorreoElectronico);

                //dir=3, est=1
                if (prol == 1 || prol == 3 && codUsuario > 0)
                {
                    UsuarioPersistente.setCarrerasUsuario(codUsuario, prol, listacarreras,null,null);
                }
            }
            catch (SqlException ex) {
                SqlError er = ex.Errors[0];

                if (er.Number == 2627)
                {
                    throw new Exception("Ya hay un usuario con el mismo correo electronico.");
                }
                else
                {
                    throw new Exception("Ha habido un error al registrar el usuario. " );
                }

               
            
            }

            return result;
        }



        public static bool registrarUsuarioBatch(List<List<string>> ListadatosUsuario)
        {
            bool result = true;
            List<Cl_Usuario> users = new List<Cl_Usuario>();
            List<string> listapwd = new List<string>();


            try
            {


                for (int i = 0; i < ListadatosUsuario.Count; i++) {
                    //Generación de la clave
                    string pwd = Cl_Usuario.CreateRandomPassword(5);
                    string pwdMD5 = Modulo.Encriptar(pwd, true);

                    //Creación del usuario
                    List<string> datosUsuario = ListadatosUsuario[i];
                    int prol = Convert.ToInt32(datosUsuario[6]);
                    Cl_Usuario objUsuario = new Cl_Usuario(datosUsuario[0], datosUsuario[1], datosUsuario[2], datosUsuario[3], datosUsuario[4], Convert.ToDateTime(datosUsuario[5]), prol, datosUsuario[7], pwdMD5);
                    users.Add(objUsuario);
                    listapwd.Add(pwd);
                }

                result = UsuarioPersistente.registrarUsuarioBatch(users, listapwd, Session.Id);

            }
            catch (SqlException ex)
            {
                SqlError er = ex.Errors[0];

                if (er.Number == 2627)
                {
                    throw new Exception("Ya hay un usuario con el mismo correo electronico.");
                }
                else
                {
                    throw new Exception("Ha habido un error al registrar el usuario. " + er.Number);
                }



            }

            return result;
        }




        public static bool actualizarUsuario(int pIdusuario, String pcedula, String pnombre, String papellido1, String papellido2,
            String pgenero, DateTime pfechNaci, int prol, String pcorreo, List<int> listacarreras)
        {
            bool result = true;
            //Se extrae el usuario de la base de datos (consistencia de datos)
            //Asi se garantiza que todos los datos vayan y no falta ninguno
            List<Cl_Usuario> listUsuario = UsuarioPersistente.buscarUsuarios("", "", "", "", "", -1, pIdusuario);
            Cl_Usuario objUsuarioBD = listUsuario[0];

            try
            {
                //Se podría optimizar comparando campos cambiantes
                if (objUsuarioBD != null)
                {
                    objUsuarioBD.Cedula = pcedula;
                    objUsuarioBD.Nombre = pnombre;
                    objUsuarioBD.PrimerApellido = papellido1;
                    objUsuarioBD.SegundoApellido = papellido2;
                    objUsuarioBD.Genero = pgenero;
                    objUsuarioBD.FechaNacimineto = pfechNaci;
                    objUsuarioBD.CorreoElectronico = pcorreo;
                    objUsuarioBD.Rol = prol;


                    //Actualiza la info del usuario
                    UsuarioPersistente.actualizarUsuario(objUsuarioBD, Session.Id);

                    CarreraPersistente persistenteCarrera = new CarreraPersistente();
                    List<EsCarrera> listaCarrerasBD = null;
                    List<int> listaIndexes = new List<int>();

       




                    if (prol == 1)
                    {
                        listaCarrerasBD =  persistenteCarrera.listarCarrerasEstudiante(objUsuarioBD.Id);

                    }
                    else if (prol == 3)
                    {
                        listaCarrerasBD = persistenteCarrera.listarCarrerasDirectorAcademico(objUsuarioBD.Id);
                    }
                    else
                    {
                        UsuarioPersistente.eliminarRelacionCarrera(objUsuarioBD);
                    }

                     if (prol == 1 || prol == 3){
                         for (int i = 0; i < listaCarrerasBD.Count; i++)
                        {
                            listaIndexes.Add(Convert.ToInt32(listaCarrerasBD[i].Id));
                        }

                        UsuarioPersistente.setCarrerasUsuario(objUsuarioBD.Id, prol, listacarreras, listaIndexes, null);
                    }
                    
                }
            }
            catch (Exception ex){

                throw ex;
            }

            return result;

        }

        public static bool eliminarusuario(int pcodigoUsuario) {
            bool result = true;

            try
            {
                //Se obtiene el usuario de la bd
                List<Cl_Usuario> listUsuario = UsuarioPersistente.buscarUsuarios("", "", "", "", "", -1, pcodigoUsuario);
                Cl_Usuario objUsuarioBD = listUsuario[0];
                UsuarioPersistente.eliminarUsuario(Session.Id, objUsuarioBD);
            }
            catch  (Exception ex){
                throw ex;
            }

            return result;
        }


        public static Dictionary<string,string> consultar(int pcodigoUsuario)
        {
            

            try
            {
                Dictionary<string, string> listaDatos = new Dictionary<string, string>();

                //Se obtiene el usuario de la bd
                List<Cl_Usuario> listUsuario = UsuarioPersistente.buscarUsuarios("", "", "", "", "", -1, pcodigoUsuario);
                Cl_Usuario objUsuarioBD = listUsuario[0];

                if (listUsuario.Count != 0)
                {
                    listaDatos.Add("id", objUsuarioBD.Id + "");
                    listaDatos.Add("cedula", objUsuarioBD.Cedula);
                    listaDatos.Add("nombre", objUsuarioBD.Nombre);
                    listaDatos.Add("ap1", objUsuarioBD.PrimerApellido);
                    listaDatos.Add("ap2", objUsuarioBD.SegundoApellido);
                    listaDatos.Add("genero", objUsuarioBD.Genero);
                    listaDatos.Add("fec_naci", objUsuarioBD.FechaNacimineto.ToString());
                    listaDatos.Add("correo", objUsuarioBD.CorreoElectronico);
                    listaDatos.Add("Rol", objUsuarioBD.Rol + "");
                    listaDatos.Add("id_persona", objUsuarioBD.IdPersona + "");
                    return listaDatos;
                }
                else
                {
                    throw new Exception("No se encontro ningún usuario.");
                }
            
                
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
        }


        public static String graduarEstudiante(int pidEstudiante, String pcedulaEstudiante)
        {
            String mensaje;
            try
            {
                UsuarioPersistente usuario = new UsuarioPersistente();

                usuario.graduarEstudiante(pidEstudiante, pcedulaEstudiante, Session.Id);

                mensaje = "¡El Estudiante se ha graduado!";

                
                return mensaje;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

        }



        public static List<Cl_Usuario> buscarEstudiante(String pcedula)
        {
            try
            {

                List<Cl_Usuario> listaUsuario = UsuarioPersistente.buscarUsuarios(pcedula, "", "", "", "", 1, -1);
                return listaUsuario;
            }
            catch (Exception)
            {
                throw;
            }

        }


        public static bool buscarEstudianteGraduado(String cedula)
        {
            try
            {
                bool existe = UsuarioPersistente.buscarEstudianteGraduado(cedula);
                return existe;
            }
            catch (Exception)
            {
                throw;
            }

        }

        public static List<Cl_Usuario> buscarProfesor(String pcedula)
        {
            try
            {

                List<Cl_Usuario> listaUsuario = UsuarioPersistente.buscarUsuarios(pcedula, "", "", "", "", 2, -1);
                return listaUsuario;
            }
            catch (Exception)
            {
                throw;
            }

        }



        /// <summary>
        /// Método de la clase encargoado de listar los estudiantes de un grupo
        /// </summary>
        /// <param name="pIdGrupo">Id del grupo, tipo int</param>
        /// <remarks></remarks>
        public static List<Informacion> listarEstudiantesGrupo(int pIdGrupo) 
        {
            try
            {
                UsuarioPersistente persistenteUsuario = new UsuarioPersistente();
                List<Informacion> datosEstudiantes = new List<Informacion>();
                
                List<Cl_Estudiante> estudiantes = new List<Cl_Estudiante>();
                estudiantes = persistenteUsuario.listarEstudiantesGrupo(pIdGrupo);

                if (estudiantes != null)
                {
                    foreach (Cl_Estudiante estudiante in estudiantes)
                    {
                        EsUsuario temp = new EsUsuario(estudiante.Id, estudiante.Cedula, estudiante.Nombre,
                                            estudiante.PrimerApellido, estudiante.SegundoApellido,
                                            estudiante.Genero, estudiante.FechaNacimineto.ToShortDateString(),
                                            estudiante.Rol, estudiante.CorreoElectronico, estudiante.Contrasena);

                        datosEstudiantes.Add(temp);
                    }

                    return datosEstudiantes;
                }
                else
                {
                    throw new Exception("El grupo no tiene estudiantes.");
                }
            }       

            catch (Exception ex)
            {
                throw ex; 
            }

        }



        public static List<Informacion> listarEstudiantesForo(int pIdForo)
        {
            Cl_Foro foro = new ForoPersistente().buscarForoPorId(pIdForo);
            List<Cl_Estudiante> estudiantes = foro.Grupo.Estudiantes;
            List<Informacion> datosEstudiantes = new List<Informacion>();

            foreach (Cl_Estudiante estudiante in estudiantes)
            {
                EsUsuario temp = new EsUsuario(estudiante.Id, estudiante.Cedula, estudiante.Nombre,
                                    estudiante.PrimerApellido, estudiante.SegundoApellido,
                                    estudiante.Genero, estudiante.FechaNacimineto.ToShortDateString(),
                                    estudiante.Rol, estudiante.CorreoElectronico, estudiante.Contrasena);

                datosEstudiantes.Add(temp);
            }

            return datosEstudiantes;
        }
        /// <summary>
        /// Método encargado de conseguir todos los profesores de un grupo.
        /// </summary>
        /// <param name="pIdGrupo">Codigo del Grupo, tipo int</param>
        /// <remarks></remarks>
        public static List<Informacion> listarProfesoresDeUnGrupo(int pIdGrupo)
        {
            try
            {
                List<Informacion> profesores = new List<Informacion>();
                GrupoPersistente persistenteGrupo = new GrupoPersistente();
                CL_Grupo grupo = persistenteGrupo.buscarGrupoPorId(pIdGrupo);

                foreach (Cl_Docente profesor in grupo.Profesores)
                {
                    EsUsuario temp = new EsUsuario(profesor.Id, profesor.Cedula, profesor.Nombre,
                                       profesor.PrimerApellido, profesor.SegundoApellido,
                                       profesor.Genero, profesor.FechaNacimineto.ToShortDateString(),
                                       profesor.Rol, profesor.CorreoElectronico, profesor.Contrasena);
                    
                    profesores.Add(temp);
                }
           
                return profesores;

            }
            catch (Exception ex)
            {

                throw ex;
            }

        }



        /// <summary>
        /// Método de la clase que busca un usuario por cedula y rol de usuario.
        /// </summary>
        /// <param name="pCedula">Cedula de la persona, tipo string</param>
        /// <param name="pRol">Rol del usuario, tipo int</param>
        /// <remarks></remarks>
        public static Dictionary<String, Object> buscarUsuarioPorCedula(string pCedula, int pRol)
        {
            try
            {
                Dictionary<String, Object> datosEstudiante = new Dictionary<String, Object>();
                UsuarioPersistente persistenteUsuario = new UsuarioPersistente();
                Cl_Usuario usuario = persistenteUsuario.buscarPorCedula(pCedula, pRol);
                if (usuario != null)
                {
                    datosEstudiante.Add("id", usuario.Id);
                    datosEstudiante.Add("cedula", usuario.Cedula + "");
                    datosEstudiante.Add("nombre", usuario.Nombre);
                    datosEstudiante.Add("ap1", usuario.PrimerApellido);
                    datosEstudiante.Add("ap2", usuario.SegundoApellido);
                    datosEstudiante.Add("genero", usuario.Genero);
                    datosEstudiante.Add("fechaNac", usuario.FechaNacimineto);
                    datosEstudiante.Add("correo", usuario.CorreoElectronico);
                    datosEstudiante.Add("contrasenia", usuario.Contrasena);
                    datosEstudiante.Add("rol", usuario.Rol + "");

                    return datosEstudiante;
                }
                else
                {
                    throw new Exception("No se encontro ninguna persona con ese número de cédula.");
                }
                
            }
            catch (Exception ex)
            {
                
                throw ex;
            }

            

        }



        /// <summary>
        /// Método de la clase encargado de cambiar las carreras del un estudiante.
        /// </summary>
        /// <param name="pIdEstudiante">pIdEstudiante, tipo int</param>
        /// <param name="pIdsAp">Ids de las  carreras seleccionadas, tipo List</int></param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        public static String cambiarCarrerasDeEstudiante(int pIdEstudiante, List<int> pIdsAp)
        {
            try
            {
                int idUsuario = Session.Id;
                CarreraPersistente persistenteCarrera = new CarreraPersistente();
                List<int> idsBD = persistenteCarrera.buscarIdsCarrerasDeEstudiante(pIdEstudiante);
                persistenteCarrera.cambiarCarrerasEstudiante(pIdEstudiante, pIdsAp, idsBD, idUsuario);
                return "Las carreras del estudiante han sido cambiadas.";
            }
            catch (Exception ex)
            {

                throw ex;
            }


        }



        /// <summary>
        /// Método de la clase encargada de modificar una nueva Carrera a la DB 
        /// </summary>
        /// <param name="pcodigoCurso">Codigo de la Carrera, tipo String</param>
        /// <param name="pnombre">Nombre de la Carrera, tipo String</param>
        /// <param name="pdescripcion">Descripcion de la carrera, tipo String</param>
        /// <param name="pestado">Estado de la carrera, tipo Byte</param>
        /// <remarks></remarks>
        public static List<Cl_Usuario> buscarUsuario(String pcedula)
        {
            try
            {
                UsuarioPersistente persistenteUsuario = new UsuarioPersistente();
                List<Cl_Usuario> listaUsuario = UsuarioPersistente.buscarUsuarios(pcedula, "", "", "", "", -1, -1);

                if (listaUsuario.Count != 0)
                {
                    return listaUsuario;
                }
                else
                {
                    throw new Exception("No se encontró ningún usuario con la cédula ingresada.");

                }
                
            }
            catch (Exception)
            {
                throw;
            }

        }


        /// <summary>
        /// Método de la clase encargada listar todos los profesores de la BD
        /// </summary>
        /// <remarks></remarks>
        public static List<Informacion> listarTodosLosProfesores()
        {
            try
            {
                UsuarioPersistente persistente = new UsuarioPersistente();
                List<Cl_Docente> profesores = UsuarioPersistente.buscarDocentes();
                List<Informacion> datosProfesores = new List<Informacion>();

                if (profesores.Count !=0)
                {
                    foreach (Cl_Docente profesor in profesores)
                    {
                        EsUsuario temp = new EsUsuario(profesor.Id, profesor.Cedula, profesor.Nombre,
                                               profesor.PrimerApellido, profesor.SegundoApellido,
                                               profesor.Genero, profesor.FechaNacimineto.ToShortDateString(),
                                               profesor.Rol, profesor.CorreoElectronico, profesor.Contrasena);

                        datosProfesores.Add(temp);

                    }
                }
                else
                {
                    throw new Exception("No hay profesores registrados en el sistema.");
                }
                   return datosProfesores;
                      
            }
            catch (Exception ex )
            {
                
                throw ex;
            } 

           

        }


        /// <summary>
        /// Método de la clase encargada listar todos los roles
        /// </summary>
        /// <remarks></remarks>
        public static List<Informacion> listarRoles()
        {
            List<Informacion> ListaResult = new List<Informacion>();
            List<EsRol> listaRoles=UsuarioPersistente.listarRoles();

            if (listaRoles.Count != 0)
            {
                foreach (EsRol item in listaRoles)
                {
                    ListaResult.Add(item);
                }

                return ListaResult;
            }
            else
            {
                throw new Exception("No hay roles registrados en el sistema.");
            }
            
        }


        /// <summary>
        /// Método de la clase que busca los usuario por diferentes criterios
        /// </summary>
        /// <remarks></remarks>
        public static List<Cl_Usuario> buscarUsuario(String pcedula, String pnombre,String pap1, String pap2,int prol,String pcorreo)
        {
            try
            {
                UsuarioPersistente persistenteUsuario = new UsuarioPersistente();
                List<Cl_Usuario> listaUsuario = UsuarioPersistente.buscarUsuarios(pcedula, pnombre, pap1, pap2, pcorreo, prol, -1);

                if (listaUsuario.Count != 0)
                {
                    return listaUsuario;
                }
                else
                {
                    throw new Exception("No se encontraron usuarios con los criterios de busqueda ingresados.");

                }
            }
            catch (Exception)
            {
                throw;
            }

        }



        public static bool iniciarSesion(String pcorreo, String pcontrasenna)
        {

            bool result;
            result = false;

            try
            {
                String correo = pcorreo;
                String contrasenna;
                List<Cl_Usuario> listaUsuario = buscarUsuario("", "", "", "", -1, pcorreo);
                Cl_Usuario usuario = listaUsuario[0];

                contrasenna = Modulo.Encriptar(pcontrasenna, true);

                if (usuario.Contrasena == contrasenna & usuario.CorreoElectronico == correo)
                {
                    Session.Id = usuario.Id;
                    Session.NombreCompleto = usuario.Nombre + " " + usuario.PrimerApellido + " " + usuario.SegundoApellido;
                    Session.Rol = usuario.Rol;
                    result = true;
                }


            }
            catch
            {
                result = false;
            }

            return result;
        }


        public static List<Informacion> listarDirectoresAcademicos()
        {

            try
            {
                UsuarioPersistente persitente = new UsuarioPersistente();
                List<EsUsuario> listTemp = persitente.buscarDirectoresAcademicos();
                List<Informacion> datosUsuarios = new List<Informacion>();

                if (listTemp.Count == 0)
                {
                    throw new Exception("No hay directores académicos registrados en el sistema.");
                }

                foreach (EsUsuario temp in listTemp)
                {
                    datosUsuarios.Add(temp);
                }

                return datosUsuarios;
            }
            catch (Exception)
            {

                throw;
            }

        }


        public static List<Dictionary<String, Object>> listarUsuariosConBlog()
        {

            try
            {
                UsuarioPersistente persitente = new UsuarioPersistente();
                List<EsUsuario> usuarios = persitente.buscarUsuariosConBlog();
                List<Dictionary<String, Object>> datosUsuarios = new List<Dictionary<String, Object>>();

                Dictionary<String, Object> usuario = null;
                
                if (usuarios.Count == 0)
                {
                    throw new Exception("No hay usuarios con blog");
                }

                foreach (EsUsuario temp in usuarios)
                {
                    usuario = new Dictionary<String, Object>();
                    usuario.Add("id", temp.Id);
                    usuario.Add("cedula", temp.Contrasena);
                    usuario.Add("nombre", temp.Nombre);
                    
                    datosUsuarios.Add(usuario);
                }

                return datosUsuarios;
            }
            catch (Exception)
            {

                throw;
            }

        }
    }
}
